package com.swak.vertx.invoker;

import java.lang.reflect.Method;
import java.util.function.Function;

import com.swak.entity.Model;
import com.swak.entity.Result;
import com.swak.utils.StringUtils;
import com.swak.vertx.transport.multipart.MultipartFile;
import com.swak.vertx.transport.multipart.PlainFile;

/**
 * InvokerHandler 和 MethodHandler 的结合
 *
 * @author: lifeng
 * @date: 2020/3/29 19:45
 */
public class FluxMethodInvoker extends MethodInvoker implements FluxInvoker {

	private final String address;

	public FluxMethodInvoker(Class<?> clazz, Object bean, Method method) {
		super(clazz, bean, method);
		this.address = this.initAddress(clazz);
	}

	/**
	 * 初始化地址
	 */
	private String initAddress(Class<?> type) {

		/*
		 * 优先使用接口: 要排除  Spring 的接口
		 */
		Class<?>[] interfacesClasses = type.getInterfaces();
		if (interfacesClasses != null && interfacesClasses.length > 0) {
			for (Class<?> inter : interfacesClasses) {
				if (inter.getName().startsWith("org.springframework.")) {
					continue;
				}
				type = inter;
				break;
			}
		}

		/*
		 * 返回服务的地址
		 */
		return this.getAddress(type, StringUtils.EMPTY);
	}

	/**
	 * 通过消息发送给 服务
	 */
	@Override
	public Object doInvoke(Object[] args) {
		return this.doRemoteInvoke(address, methodMeta, args).thenApply(Handler);
	}

	/**
	 * 优化 Lambda 的性能
	 */
	private static final Function<Object, Object> Handler = FluxMethodInvoker::wrapResult;

	private static Object wrapResult(Object result) {
		if (result == null || isJson(result.getClass())) {
			return Result.success(result);
		}
		return result;
	}

	private static boolean isJson(Class<?> type) {
		return !(type == Result.class || type == Model.class || type == PlainFile.class || type == MultipartFile.class
				|| type == String.class);
	}
}